#include "Activation.h"

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Activation
 *      Method:  Activation
 * Description:  Constrói uma função de ativação passando seu tipo e um parâmetro opcional
 *--------------------------------------------------------------------------------------
 */
Activation::Activation(int type, double param)
{
    this->type = type;
    this->param = param;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Activation
 *      Method:  calc
 * Description:  Chama a função de ativação correspondente
 *--------------------------------------------------------------------------------------
 */
double Activation::calc(double x)
{
    switch(type)
    {
        // Função degrau: f(x) = 1 caso x > 0; f(x) = 0 caso contrário
        case STEP:
            return (x > 0) ? 1 : 0;

        // Função pseudo-linear: f(x) = 1 caso x > 1; f(x) = 0 caso x < 0; f(x) = x caso contrário
        case PSEUDO_LINEAR:
            if(x > 1)
                return 1;
            else if(x <= 0)
                return 0;
            else
                return x;

        // Função sigmóide: f(x) = 1/(1+e^(-c*x))
        case SIGMOID:
            return 1 / (1 + exp(-param * x));

        // Função tangente hiperbólica: f(x) = tanh(x)
        case HYPERBOLIC:
            return tanh(x);

        // Função logística: f(x) = (1+e^-x)^-1
        case LOGISTIC:
            return 1 / (1 + exp(-x));

        default:
            return 0;
    }
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Activation
 *      Method:  derivate
 * Description:  Chama a derivada da função de ativação correspondente
 *--------------------------------------------------------------------------------------
 */
double Activation::derivate(double x)
{
    double aux;
    switch(type)
    {
        // Derivada da tangente hiperbólica: f(x) = sech(x)^2
        case HYPERBOLIC:
            aux = 2 * cosh(x) / (cosh(2 * x) + 1);
            return aux * aux;
            break;

        // Derivada da função logística: f(x) = e^-x / (e^-x+1)^2
        case LOGISTIC:
            aux = exp(x);
            return aux / ((aux + 1) * (aux + 1));
            break;

        default:
            return 0;
    }
}

